home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Tools 2
/
Amiga Tools 2.iso
/
golded
/
api
/
dock
/
main.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-02-17
|
16KB
|
516 lines
/* -----------------------------------------------------------------------------
GoldED API client example code, ©1995 Dietmar Eilert. Dice:
dcc main.c -// -mRR -r -proto -2.0 -l tmsr.lib -l reqtoolssr.lib -o ram:dock
Note: Compiling this code requires ToolManger includes & ToolManager linker
libraries. ToolManager is ©1990-1995 Stefan Becker.
The following example uses synchronous ARexx communication: Requests are
PutMsg()'ed to GoldED's port, followed by a WaitPort() to get the editor's
response. This works fine since we need no ARexx communication after the API
link has been established. If there were ARexx communication AFTER the link has
been established (i.e. after sending the 'API PORT=...' command to register
with GoldED), we would have to use an asynchronous design beeing capable of
answering incoming API messages while waiting for completion of ARexx requests
sent to GoldED.
------------------------------------------------------------------------------
*/
/// "includes"
#define Prototype extern
#include <exec/exec.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <dos/dos.h>
#include <dos/rdargs.h>
#include <intuition/intuition.h>
#include <workbench/startup.h>
#include <rexx/errors.h>
#include <rexx/rxslib.h>
#include <libraries/reqtools.h>
#include <utility/tagitem.h>
#include <clib/toolmanager_protos.h>
#include <clib/exec_protos.h>
#include <clib/dos_protos.h>
#include <clib/intuition_protos.h>
#include <clib/rexxsyslib_protos.h>
#include <clib/reqtools_protos.h>
#include "golded:api/include/golded.h"
// ToolManager objects are a combination of action/image/sound:
// Les objets ToolManager sont une combinaison d'objets action/image/son:
struct tmTool {
APTR exec;
APTR icon;
APTR sound;
};
struct Library *ReqToolsBase;
Prototype void main(int, char **);
Prototype void HandleAPI(void *, char *, struct TagItem *, UWORD, UWORD);
Prototype ULONG *SendRexxCommand(char *, char *, struct MsgPort *, char *);
Prototype char *xsprintf(char *, char *);
Prototype struct TagItem *ReadConfig(char *, void *, char *, UWORD *, UWORD *);
///
/// "main"
void
main(int argc, char **argv)
{
const char *version = "$VER: dock 1.6 (" __COMMODORE_DATE__ ")";
struct RDArgs *rdArgs;
ULONG args[] = { 0, 0 };
if (rdArgs = ReadArgs("CONFIG,HOST/K/A", args, NULL)) {
UBYTE *prefs;
UWORD try;
void *handle;
prefs = args[0] ? (char *)args[0] : "progdir:dock.prefs";
// wait for ToolManager startup
for (try = 20; !(handle = AllocTMHandle()) && try; try--)
Delay(10);
if (handle) {
struct TagItem *dock;
UWORD dockX = ~0, dockY = ~0;
if (dock = ReadConfig(prefs, handle, (char *)args[1], &dockX, &dockY))
HandleAPI(handle, (char *)args[1], dock, dockX, dockY);
FreeTMHandle(handle);
}
else
puts("got no TM handle ?!");
FreeArgs(rdArgs);
}
else
puts("syntax error: dock [<config>] HOST=<host>");
exit(0);
}
int
wbmain(struct WBStartup *startup)
{
if (ReqToolsBase = OpenLibrary("reqtools.library", 37)) {
rtEZRequestTags("No executable - to be used as API client", "OK", NULL, NULL, TAG_DONE);
CloseLibrary(ReqToolsBase);
}
}
///
/// "read config"
/* -------------------------------- ReadConfig ---------------------------------
Read config file. Return ready-to-use tag array for dock creation or NULL.
Write dock screen position to <dockX>/<dockY>.
*/
struct TagItem *
ReadConfig(prefs, handle, host, dockX, dockY)
void *handle;
char *prefs, *host;
UWORD *dockX, *dockY;
{
struct TagItem *dock = NULL;
BPTR config;
if (config = Open(prefs, MODE_OLDFILE)) {
struct RDArgs *rdArgs;
if (rdArgs = AllocDosObject(DOS_RDARGS, NULL)) {
static char buffer[256];
UWORD columns, entries, orientation;
columns = 1;
orientation = 0;
entries = 0;
while (FGets(config, buffer, 255)) {
char *cmd;
for (strcat(buffer, "\12"), cmd = buffer; *cmd && (*cmd != ';'); ++cmd) {
if ((*cmd != ' ') && (*cmd != 10)) {
ULONG n, argArray[] = { 0, 0, 0, 0, 0, 0 };
struct RDArgs *args;
static struct parser { char *command; char *template; } parser[] = {
"ADD", "COMMAND/K/A,AREXX/S,EXEC/S,DIR/K,OUTPUT/K,ICON/K/A",
"DOCK", "X/N,Y/N,HORIZONTAL/S,COLUMNS/N",
NULL
};
for (n = 0; parser[n].command; ++n) {
if (!memcmp(cmd, parser[n].command, strlen(parser[n].command))) {
cmd += strlen(parser[n].command);
rdArgs->RDA_Source.CS_Buffer = cmd;
rdArgs->RDA_Source.CS_Length = strlen(cmd);
rdArgs->RDA_Source.CS_CurChr = 0;
rdArgs->RDA_DAList = NULL;
rdArgs->RDA_Buffer = NULL;
if (args = ReadArgs(parser[n].template, argArray, rdArgs)) {
if (n == 0) {
char execName[8], iconName[8];
struct TagItem iconTags[] = { TMOP_File, strdup((char *)argArray[5]), TMOP_Data, NULL, TAG_DONE };
struct TagItem execTags[] = {
TMOP_Command, xsprintf((char *)argArray[0], host),
TMOP_ExecType, argArray[1] ? TMET_ARexx : TMET_CLI,
TMOP_Stack, 8192,
TMOP_CurrentDir, argArray[3] ? strdup((char *)argArray[3]) : NULL,
TMOP_Output, argArray[4] ? strdup((char *)argArray[4]) : NULL,
TAG_DONE
};
sprintf(execName, "e%ld", entries);
sprintf(iconName, "i%ld", entries++);
CreateTMObjectTagList(handle, strdup(execName), TMOBJTYPE_EXEC, execTags);
CreateTMObjectTagList(handle, strdup(iconName), TMOBJTYPE_IMAGE, iconTags);
}
else if (n == 1) {
if (argArray[0])
*dockX = *(ULONG *)argArray[0];
if (argArray[1])
*dockY = *(ULONG *)argArray[1];
if (argArray[2])
orientation = 1;
if (argArray[3])
columns = *(ULONG *)argArray[3];
}
FreeArgs(args);
}
}
}
break;
}
}
if (entries) {
if (dock = (struct TagItem *)calloc((entries + 9) * sizeof(struct TagItem), 1)) {
UWORD n;
dock[0].ti_Tag = TMOP_PubScreen;
dock[1].ti_Tag = TMOP_LeftEdge;
dock[2].ti_Tag = TMOP_TopEdge;
dock[3].ti_Tag = TMOP_Activated;
dock[4].ti_Tag = TMOP_Centered;
dock[5].ti_Tag = TMOP_Columns;
dock[6].ti_Tag = TMOP_Vertical;
dock[7].ti_Tag = TMOP_Text;
dock[8].ti_Tag = TAG_DONE;
dock[3].ti_Data = TRUE;
dock[5].ti_Data = columns;
dock[6].ti_Data = orientation;
for (n = 0; n < entries; ++n) {
struct tmTool *tool;
if (tool = (struct tmTool *)calloc(sizeof(struct tmTool), 1)) {
if ((tool->exec = calloc(8, 1)) && (tool->icon = calloc(8, 1))) {
sprintf((char *)tool->exec, "e%ld", n);
sprintf((char *)tool->icon, "i%ld", n);
dock[8 + n].ti_Tag = TMOP_Tool;
dock[8 + n].ti_Data = tool;
}
}
}
}
}
}
FreeDosObject(DOS_RDARGS, rdArgs);
}
Close(config);
}
else
puts("dock.prefs missing");
return(dock);
}
///
/// "API management"
/* --------------------------------- HandleAPI ---------------------------------
Register with GoldED & handle incoming API messages.
*/
void
HandleAPI(handle, host, dock, dockX, dockY)
struct TagItem *dock;
char *host;
void *handle;
UWORD dockX, dockY;
{
struct MsgPort *replyPort;
if (replyPort = CreateMsgPort()) {
char command[255];
ULONG *result;
sprintf(command, "API PORT=%ld CLASS=%ld", replyPort, API_CLASS_ROOT | API_CLASS_SCREEN);
if (result = SendRexxCommand(host, command, replyPort, NULL)) {
if (*result == RC_OK) {
BOOL active = TRUE;
do {
struct APIMessage *apiMsg, *nextMsg;
// API messages might already have arrived since SendRexxCommand() only pulls one message of the port
while (!(apiMsg = (struct APIMessage *)GetMsg(replyPort)))
WaitPort(replyPort);
do {
for (nextMsg = apiMsg; nextMsg; nextMsg = nextMsg->api_Next) {
if (nextMsg->api_State == API_STATE_NOTIFY) {
switch (nextMsg->api_Class) {
case API_CLASS_ROOT:
switch (nextMsg->api_Action) {
case API_ACTION_DIE:
active = FALSE;
DeleteTMObject(handle, "dock1");
break;
case API_ACTION_INTRODUCE:
static struct TagItem tags[] = {
API_Client_Name, "dock",
API_Client_Copyright, "©1995 Dietmar Eilert",
API_Client_Purpose, "ToolManager dock for GoldED",
TAG_DONE
};
nextMsg->api_Data = tags;
break;
default:
nextMsg->api_Error = API_ERROR_UNKNOWN;
}
break;
case API_CLASS_SCREEN:
switch (nextMsg->api_Action) {
case API_ACTION_HIDE:
DeleteTMObject(handle, "dock1");
break;
case API_ACTION_SHOW:
struct Screen *screen;
if (screen = LockPubScreen(nextMsg->api_Global->F_ScrnName)) {
dock[0].ti_Data = nextMsg->api_Global->F_ScrnName;
dock[1].ti_Data = (dockX == ~0) ? screen->Width : dockX;
dock[2].ti_Data = (dockY == ~0) ? screen->BarHeight + ((screen->BitMap.Depth == 1) ? 2 : 1) : dockY;
UnlockPubScreen(NULL, screen);
}
CreateTMObjectTagList(handle, "dock1", TMOBJTYPE_DOCK, dock);
break;
default:
nextMsg->api_Error = API_ERROR_UNKNOWN;
}
break;
default:
nextMsg->api_Error = API_ERROR_UNKNOWN;
}
}
}
ReplyMsg((struct Message *)apiMsg);
} while (apiMsg = (struct APIMessage *)GetMsg(replyPort));
} while (active);
}
}
DeleteMsgPort(replyPort);
}
}
///
/// "misc"
/* --------------------------------- xsprintf ----------------------------------
sprintf frontend (malloc buffer); limited to string insertion into string
*/
char *
xsprintf(mask, var)
char *mask, *var;
{
char *buffer;
if (buffer = malloc(strlen(mask) + strlen(var)))
sprintf(buffer, mask, var);
return(buffer);
}
///
/// "ARexx"
/* ---------------------------------- SendRexxCommand -------------------------
Send ARexx message & wait for answer. Return pointer to result or NULL.
*/
ULONG *
SendRexxCommand(port, cmd, replyPort, buffer)
char *cmd, *port, *buffer;
struct MsgPort *replyPort;
{
struct MsgPort *rexxport;
Forbid();
if (rexxport = FindPort(port)) {
struct RexxMsg *rexxMsg, *answer;
if (rexxMsg = CreateRexxMsg(replyPort, NULL, NULL)) {
if (rexxMsg->rm_Args[0] = CreateArgstring(cmd, strlen(cmd))) {
static ULONG result;
rexxMsg->rm_Action = RXCOMM | RXFF_RESULT;
PutMsg(rexxport, &rexxMsg->rm_Node);
do {
WaitPort(replyPort);
if (answer = (struct RexxMsg *)GetMsg(replyPort))
result = answer->rm_Result1;
} while (!answer);
Permit();
if (answer->rm_Result1 == RC_OK) {
if (answer->rm_Result2) {
if (buffer)
strcpy(buffer, (char *)answer->rm_Result2);
DeleteArgstring((char *)answer->rm_Result2);
}
}
DeleteArgstring((char *)ARG0(answer));
DeleteRexxMsg(answer);
return(&result);
}
}
}
Permit();
return(NULL);
}
///